﻿using CommunityToolkit.Mvvm.Messaging.Messages;
using CommunityToolkit.Mvvm.Messaging;
using FTD2XX_NET;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using TMI85303.UI.Messages;
using System.Windows.Controls;
using TMI85303.UI.ViewModels;
using System.Windows.Forms;

namespace TMI85303.Utils
{
    public class ReadWrite
    {
        #region ft4222h初始化


        /*******************************FUNCTION IMPORTS FROM FTD2XX DLL*************************************/

        [DllImport("ftd2xx.dll")]
        static extern FTDI.FT_STATUS FT_CreateDeviceInfoList(ref UInt32 numdevs);

        [DllImport("ftd2xx.dll")]
        static extern FTDI.FT_STATUS FT_GetDeviceInfoDetail(UInt32 index, ref UInt32 flags, ref FT4222_Device chiptype, ref UInt32 id, ref UInt32 locid, byte[] serialnumber, byte[] description, ref IntPtr ftHandle);

        //[DllImportAttribute("ftd2xx.dll", CallingConvention = CallingConvention.Cdecl)]
        [DllImport("ftd2xx.dll")]
        static extern FTDI.FT_STATUS FT_OpenEx(IntPtr pvArg1, int dwFlags, ref IntPtr ftHandle);
        //[DllImportAttribute("ftd2xx.dll", CallingConvention = CallingConvention.Cdecl)]
        [DllImport("ftd2xx.dll")]
        static extern FTDI.FT_STATUS FT_Close(IntPtr ftHandle);


        const byte FT_OPEN_BY_SERIAL_NUMBER = 1;
        const byte FT_OPEN_BY_DESCRIPTION = 2;
        const byte FT_OPEN_BY_LOCATION = 4;


        /*********************************FUNCTION IMPORTS FROM LibFT4222-64 DLL*******************************/

        [DllImport("LibFT4222-64.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern FT4222_STATUS FT4222_SetClock(IntPtr ftHandle, int FT4222_ClockRate);

        [DllImport("LibFT4222-64.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern FT4222_STATUS FT4222_GetClock(IntPtr ftHandle, ref FT4222_ClockRate clk);

        [DllImport("LibFT4222-64.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern FT4222_STATUS FT4222_SetSuspendOut(IntPtr ftHandle, bool enable);

        [DllImport("LibFT4222-64.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern FT4222_STATUS FT4222_SetWakeUpInterrupt(IntPtr ftHandle, bool enable);


        /**********************************I2C DLL****************************************/
        [DllImport("LibFT4222-64.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern FT4222_STATUS FT4222_I2CMaster_Init(IntPtr ftHandle, uint kbps);

        [DllImport("LibFT4222-64.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern FT4222_STATUS FT4222_I2CMaster_Read(IntPtr ftHandle, ushort slaveAddress, ref byte readBuffer, ushort bufferSize, ref ushort sizeTransferred);

        [DllImport("LibFT4222-64.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern FT4222_STATUS FT4222_I2CMaster_Write(IntPtr ftHandle, ushort slaveAddress, ref byte writeBuffer, ushort bufferSize, ref ushort sizeTransferred);

        [DllImport("LibFT4222-64.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern FT4222_STATUS FT4222_I2CMaster_WriteEx(IntPtr ftHandle, ushort slaveAddress, byte flag, byte[] writeBuffer, ushort bufferSize, ref ushort sizeTransferred);

        [DllImport("LibFT4222-64.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern FT4222_STATUS FT4222_I2CMaster_ReadEx(IntPtr ftHandle, ushort slaveAddress, byte flag, byte[] readBuffer, ushort bufferSize, ref ushort sizeTransferred);

        [DllImport("LibFT4222-64.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern FT4222_STATUS FT4222_I2CMaster_GetStatus(IntPtr ftHandle, ref byte controllerStatus);

        [DllImport("LibFT4222-64.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern FT4222_STATUS FT4222_I2CMaster_Reset(IntPtr ftHandle);

        // FT4222 Device status
        public enum FT4222_STATUS
        {
            FT4222_OK,
            FT4222_INVALID_HANDLE,
            FT4222_DEVICE_NOT_FOUND,
            FT4222_DEVICE_NOT_OPENED,
            FT4222_IO_ERROR,
            FT4222_INSUFFICIENT_RESOURCES,
            FT4222_INVALID_PARAMETER,
            FT4222_INVALID_BAUD_RATE,
            FT4222_DEVICE_NOT_OPENED_FOR_ERASE,
            FT4222_DEVICE_NOT_OPENED_FOR_WRITE,
            FT4222_FAILED_TO_WRITE_DEVICE,
            FT4222_EEPROM_READ_FAILED,
            FT4222_EEPROM_WRITE_FAILED,
            FT4222_EEPROM_ERASE_FAILED,
            FT4222_EEPROM_NOT_PRESENT,
            FT4222_EEPROM_NOT_PROGRAMMED,
            FT4222_INVALID_ARGS,
            FT4222_NOT_SUPPORTED,
            FT4222_OTHER_ERROR,
            FT4222_DEVICE_LIST_NOT_READY,

            FT4222_DEVICE_NOT_SUPPORTED = 1000,        // FT_STATUS extending message
            FT4222_CLK_NOT_SUPPORTED,     // spi master do not support 80MHz/CLK_2
            FT4222_VENDER_CMD_NOT_SUPPORTED,
            FT4222_IS_NOT_SPI_MODE,
            FT4222_IS_NOT_I2C_MODE,
            FT4222_IS_NOT_SPI_SINGLE_MODE,
            FT4222_IS_NOT_SPI_MULTI_MODE,
            FT4222_WRONG_I2C_ADDR,
            FT4222_INVAILD_FUNCTION,
            FT4222_INVALID_POINTER,
            FT4222_EXCEEDED_MAX_TRANSFER_SIZE,
            FT4222_FAILED_TO_READ_DEVICE,
            FT4222_I2C_NOT_SUPPORTED_IN_THIS_MODE,
            FT4222_GPIO_NOT_SUPPORTED_IN_THIS_MODE,
            FT4222_GPIO_EXCEEDED_MAX_PORTNUM,
            FT4222_GPIO_WRITE_NOT_SUPPORTED,
            FT4222_GPIO_PULLUP_INVALID_IN_INPUTMODE,
            FT4222_GPIO_PULLDOWN_INVALID_IN_INPUTMODE,
            FT4222_GPIO_OPENDRAIN_INVALID_IN_OUTPUTMODE,
            FT4222_INTERRUPT_NOT_SUPPORTED,
            FT4222_GPIO_INPUT_NOT_SUPPORTED,
            FT4222_EVENT_NOT_SUPPORTED,
        };

        //FT4222 Device
        public enum FT4222_Device
        {
            //
            // 摘要:
            //     FT232B or FT245B device
            FT_DEVICE_BM,
            //
            // 摘要:
            //     FT8U232AM or FT8U245AM device
            FT_DEVICE_AM,
            //
            // 摘要:
            //     FT8U100AX device
            FT_DEVICE_100AX,
            //
            // 摘要:
            //     Unknown device
            FT_DEVICE_UNKNOWN,
            //
            // 摘要:
            //     FT2232 device
            FT_DEVICE_2232,
            //
            // 摘要:
            //     FT232R or FT245R device
            FT_DEVICE_232R,
            //
            // 摘要:
            //     FT2232H device
            FT_DEVICE_2232H,
            //
            // 摘要:
            //     FT4232H device
            FT_DEVICE_4232H,
            FT_DEVICE_232H,


            FT_DEVICE_4222H_0 = 10,
            FT_DEVICE_4222H_1_2,
            FT_DEVICE_4222H_3
        }


        public enum FT4222_ClockRate
        {
            SYS_CLK_60 = 0,
            SYS_CLK_24,
            SYS_CLK_48,
            SYS_CLK_80,

        };

        // variable
        public static FTDI.FT_DEVICE_INFO_NODE devInfo = new();
        public static IntPtr ftHandle = new();
        public static FTDI.FT_STATUS ftStatus = 0;
        public static FT4222_STATUS ft42Status = 0;

        #endregion


        public static byte slaveAddr = 0x55;
        public static byte addrBit = 8;
        public static bool eepromFlag = true;
        public static bool ConnectedOk = false;

        public class FtDeviceListInforNode 
        {
            public string? Name { get; set; }
            public uint Locid { get; set; }
        } 


        #region 设备查找相关
        public static bool SearchDevList(out List<FtDeviceListInforNode> adds)
        {
            adds = new();
            UInt32 flags = 0;
            FT4222_Device chiptype = FT4222_Device.FT_DEVICE_UNKNOWN;
            UInt32 id = 0, locid = 0;
            uint numOfDevices = 0;
            byte[] sernum = new byte[16];
            byte[] desc = new byte[64];
            IntPtr ftHandle = IntPtr.Zero;

            ftStatus = FT_CreateDeviceInfoList(ref numOfDevices);
            if (numOfDevices > 0)
            {
                for (uint i = 0; i < numOfDevices; i++)
                {
                    ftStatus = FT_GetDeviceInfoDetail(i, ref flags,
                                                         ref chiptype,
                                                         ref id,
                                                         ref locid,
                                                             sernum,
                                                             desc,
                                                         ref ftHandle);
                    devInfo.SerialNumber = Encoding.ASCII.GetString(sernum, 0, 16);
                    devInfo.Description = Encoding.ASCII.GetString(desc, 0, 64);
                    devInfo.SerialNumber = devInfo.SerialNumber.Substring(0, devInfo.SerialNumber.IndexOf('\0'));
                    devInfo.Description = devInfo.Description.Substring(0, devInfo.Description.IndexOf('\0'));

                    if (FT4222_STATUS.FT4222_OK == ft42Status)
                    {
                        if (chiptype == FT4222_Device.FT_DEVICE_4222H_0

                           || chiptype == FT4222_Device.FT_DEVICE_4222H_1_2

                           || chiptype == FT4222_Device.FT_DEVICE_4222H_3)

                        {
                            if(devInfo.Description == "FT4222 A")
                            {
                                adds.Add(new() { Name = $"USB to IIC(0x{locid:X})", Locid = locid});
                            }
                        }
                    }
                }
                return true;
            }
            else return false;
        }

        public static bool ConnectDev(uint locid,uint kbps = 400)
        {
            //IntPtr init = Marshal.StringToHGlobalAnsi("FT4222 A");
            ftStatus = FT_OpenEx((IntPtr)locid, FT_OPEN_BY_LOCATION, ref ftHandle);
            //Marshal.FreeHGlobal(init);

            if (ftStatus == FTDI.FT_STATUS.FT_OK)
            {
                ft42Status = FT4222_SetClock(ftHandle, 0);
                ft42Status = FT4222_I2CMaster_Init(ftHandle, kbps);
                ConnectedOk = true;
                return true;
            }
            else 
            {
                ConnectedOk = false;
                return false;
            }
        }

        public static bool DisConnectDev()
        {
            if(!ConnectedOk) return true;
            var res = FT_Close(ftHandle) == FTDI.FT_STATUS.FT_OK;
            if(res) { ConnectedOk = false; }
            return res;
        }

        #endregion

        #region i2cRead & i2cWrite

        /**************************************************************************************************/

        public static bool i2cRead(byte slaveAddr, byte addrbit, UInt16 addr, byte[] dat, UInt32 len)
        {
            UInt32 bufOffset = 0;
            UInt16 count;
            UInt16 maxSize = 60 * 1024;

            bool result = true;
            if (len == 0) return result;

            while (len > 0)
            {
                count = (len > maxSize) ? (UInt16)maxSize : (UInt16)len;

                byte addrLen = (byte)((addrbit == 16) ? 2 : 1);

                UInt16 index = 0;

                byte[] addrBuf = new byte[addrLen];

                if (addrbit == 16)

                    addrBuf[index++] = (byte)(addr >> 8);
                addrBuf[index++] = (byte)(addr & 0xff);
                ushort sizeTransferred = 0;
                ft42Status = FT4222_I2CMaster_WriteEx(ftHandle, slaveAddr, 0x02, addrBuf, addrLen, ref sizeTransferred);

                if (ft42Status != FT4222_STATUS.FT4222_OK)
                {
                    result = false;
                    break;
                }
                byte[] rdBuf = new byte[count];
                ft42Status = 0;
                ft42Status = FT4222_I2CMaster_ReadEx(ftHandle, slaveAddr, 0x03 | 0x04, rdBuf, count, ref sizeTransferred);

                if (ft42Status != FT4222_STATUS.FT4222_OK)
                {
                    result = false;
                    break;
                }

                Buffer.BlockCopy(rdBuf, 0, dat, (int)bufOffset, count);
                bufOffset += count;
                addr += count;
                len -= count;
            }

            return result;
        }

        public static bool i2cWrite(byte slaveAddr, byte addrbit, UInt16 addr, byte[] dat, UInt32 len)
        {

            UInt32 bufOffset = 0;
            UInt16 count;
            UInt16 maxSize = 60 * 1024;
            bool result = true;
            if (len == 0) return result;

            while (len > 0)
            {
                count = (len > maxSize) ? (UInt16)maxSize : (UInt16)len;

                byte addrLen = (byte)((addrbit == 16) ? 2 : 1);

                UInt16 index = 0;

                byte[] allBuf = new byte[count + addrLen];

                if (addrbit == 16) allBuf[index++] = (byte)(addr >> 8);

                allBuf[index++] = (byte)(addr & 0xff);

                Buffer.BlockCopy(dat, (int)bufOffset, allBuf, index, count);
                ushort sizeTransferred = 0;
                ft42Status = 0;
                ft42Status = FT4222_I2CMaster_WriteEx(ftHandle, slaveAddr, 0x06, allBuf, (UInt16)allBuf.Length, ref sizeTransferred);

                if (ft42Status != FT4222_STATUS.FT4222_OK)
                {
                    result = false;
                    break;
                }

                do
                {
                    byte controlStat = 0;

                    // to check if i2c progress succeed
                    FT4222_I2CMaster_GetStatus(ftHandle, ref controlStat);
                    if (controlStat == 0x20) break;

                    if (FT4222_STATUS.FT4222_OK == ft42Status)
                    {
                        // is there any error occur
                        Console.WriteLine("I2CM Write status:" + controlStat);

                        if ((controlStat & 0x02) == 0x02)
                        {
                            // error happen
                            // reset i2c master to default
                            FT4222_I2CMaster_Reset(ftHandle);
                            result = false;
                            break;
                        }
                    }
                    else
                    {
                        // get status failed
                        result = false;
                        break;
                    }

                } while (true);

                if (result == false) break;

                bufOffset += count;
                addr += count;
                len -= count;
            }
            return result;
        }

        /**************************************************************************************************/

        #endregion

        public static bool lockTrim()
        {
            return WriteReg(191, 0, 2);
        }

        public static bool unlockTrim()
        {
            return WriteReg(191, 43448, 2);
        }

        public static int ReadReg(ushort readAddr, uint numDataBytesToRead)
        {
            int result = default;
            if (MainWindowVM.OutlineGlobalFlag)
            {
                string format = numDataBytesToRead == 1 ? "X2" : (numDataBytesToRead == 2 ? "X4" : "X6");
                Log.Information(" Read" + readAddr.ToString() + "：0x" + result.ToString($"{format}") + "(" + result.ToString() + ")\r\n");
            }
            else
            {
                byte[] dataOut = new byte[3];
                if (numDataBytesToRead >= 1 && numDataBytesToRead <= 3 && i2cRead(slaveAddr, addrBit, readAddr, dataOut, numDataBytesToRead))
                {
                    for (int i = 0; i < numDataBytesToRead; i++)
                    {
                        result = (result << 8) + dataOut[i];
                    }
                    Log.Information($" Read{readAddr}:0x{result.ToString($"X{numDataBytesToRead * 2}")}({result})\r\n");
                }
            }
            return result;
        }

        public static bool TryReadReg(ushort readAddr, uint numDataBytesToRead,out int result)
        {
            result = default;
            if (MainWindowVM.OutlineGlobalFlag)
            {
                string format = numDataBytesToRead == 1 ? "X2" : (numDataBytesToRead == 2 ? "X4" : "X6");
                Log.Information(" Read" + readAddr.ToString() + "：0x" + result.ToString($"{format}") + "(" + result.ToString() + ")\r\n");
                return false;
            }
            else
            {
                byte[] dataOut = new byte[3];
                if (numDataBytesToRead >= 1 && numDataBytesToRead <= 3 && i2cRead(slaveAddr, addrBit, readAddr, dataOut, numDataBytesToRead))
                {
                    for (int i = 0; i < numDataBytesToRead; i++)
                    {
                        result = (result << 8) + dataOut[i];
                    }
                    Log.Information($" Read{readAddr}:0x{result.ToString($"X{numDataBytesToRead * 2}")}({result})\r\n");
                    return true;
                }
            }
            return false;
        }

        public static int ReadRegNoLog(ushort readAddr, uint numDataBytesToRead)
        {
            int result = default;

            if (!MainWindowVM.OutlineGlobalFlag)
            {
                byte[] dataOut = new byte[3];
                if (numDataBytesToRead >= 1 && numDataBytesToRead <= 3 && i2cRead(slaveAddr, addrBit, readAddr, dataOut, numDataBytesToRead))
                {
                    for (int i = 0; i < numDataBytesToRead; i++)
                    {
                        result = (result << 8) + dataOut[i];
                    }
                }
            }
            return result;
        }

        public static bool TryReadRegNoLog(ushort readAddr, uint numDataBytesToRead,out int result)
        {
            result = default;
            if (!MainWindowVM.OutlineGlobalFlag)
            {
                byte[] dataOut = new byte[3];
                if (numDataBytesToRead >= 1 && numDataBytesToRead <= 3 && i2cRead(slaveAddr, addrBit, readAddr, dataOut, numDataBytesToRead))
                {
                    for (int i = 0; i < numDataBytesToRead; i++)
                    {
                        result = (result << 8) + dataOut[i];
                    }
                    return true;
                }
            }

            return MainWindowVM.OutlineGlobalFlag;//离线模式时，默认返回true；不是离线模式时，代表上面读取失败
        }


        public static bool WriteReg(ushort writeAddr, int writeData, uint numDataBytesToWrite)
        {
            byte[] array = new byte[3];

            if (numDataBytesToWrite == 1)
            {
                array[0] = (byte)(writeData & 0xFF);
            }else if (numDataBytesToWrite == 2)
            {
                array[0] = (byte)((writeData >> 8) & 0xFF);
                array[1] = (byte)(writeData & 0xFF);
            }else if (numDataBytesToWrite == 3)
            {
                array[0] = (byte)((writeData >> 16) & 0xFF);
                array[1] = (byte)((writeData >> 8) & 0xFF);
                array[2] = (byte)(writeData & 0xFF);
            }

            if (MainWindowVM.OutlineGlobalFlag)
            {
                switch (numDataBytesToWrite)
                {
                    case 1:
                        Log.Information(" Write" + writeAddr.ToString() + "：0x" + writeData.ToString("X2") + "(" + writeData.ToString() + ")\r\n");
                        break;
                    case 2:
                        Log.Information(" Write" + writeAddr.ToString() + "：0x" + writeData.ToString("X4") + "(" + writeData.ToString() + ")\r\n");
                        if (writeAddr != 161 && writeAddr != 162 && writeAddr != 163
                            && writeAddr >= 64 && writeAddr <= 95)
                        {
                            WeakReferenceMessenger.Default.Send<UpdateMTPDataMesg, int>(new(writeAddr - 64, writeData), (int)MesgToken.MTP_DATA);
                        }
                        break;
                    case 3:
                        Log.Information(" Write" + writeAddr.ToString() + "：0x" + writeData.ToString("X6") + "(" + writeData.ToString() + ")\r\n");
                        break;
                }

                return true;
            }
            else
            {
                if (i2cWrite(slaveAddr, addrBit, writeAddr, array, numDataBytesToWrite))
                {
                    if(numDataBytesToWrite == 2 && writeAddr != 161 && writeAddr != 162 && writeAddr != 163
                        && writeAddr >= 64 && writeAddr <= 95)
                    {
                        WeakReferenceMessenger.Default.Send<UpdateMTPDataMesg, int>(new(writeAddr - 64, writeData), (int)MesgToken.MTP_DATA);
                    }
                    Log.Information($" Write{writeAddr}:0x{writeData.ToString($"X{numDataBytesToWrite * 2}")}({writeData})\r\n");
                    return true;
                }
            }

            Log.Information(" " + writeAddr.ToString() + " Write failed!\r\n");
            return false;
        }


        public static bool WriteRegNoLog(ushort writeAddr, int writeData, uint numDataBytesToWrite)
        {
            byte[] array = new byte[3];

            if (numDataBytesToWrite == 1)
            {
                array[0] = (byte)(writeData & 0xFF);
            }
            if (numDataBytesToWrite == 2)
            {
                array[0] = (byte)((writeData >> 8) & 0xFF);
                array[1] = (byte)(writeData & 0xFF);
            }
            if (numDataBytesToWrite == 3)
            {
                array[0] = (byte)((writeData >> 16) & 0xFF);
                array[1] = (byte)((writeData >> 8) & 0xFF);
                array[2] = (byte)(writeData & 0xFF);
            }
            return !MainWindowVM.OutlineGlobalFlag && i2cWrite(slaveAddr, addrBit, writeAddr, array, numDataBytesToWrite);
        }


        public static void WriteEE(int writeEEAddr, int writeEEData)
        {
            if ((writeEEAddr == 0) || (writeEEAddr == 1) || (writeEEAddr == 2) ||
                (writeEEAddr == 3) || (writeEEAddr == 5) || (writeEEAddr == 28) || (writeEEAddr == 31))
            {
                return;
            }

            //  *************** 新版芯片新增 ***********
            if (!WriteReg(163, 0, 2))
            {
                return;
            }

            if (!WriteReg(162, writeEEAddr, 2))
            {
                return;
            }

            if (!WriteReg(161, 3, 2))
            {
                return;
            }
            //  ************* 新版芯片新增 *************


            if (!WriteReg(163, writeEEData, 2))
            {
                MainWindowVM.MTPchackFailed = true;
                return;
            }

            if (!WriteReg(162, writeEEAddr, 2))
            {
                MainWindowVM.MTPchackFailed = true;
                return;
            }

            WriteReg(161, 5, 2);

            if ((writeEEAddr != 28) & (writeEEAddr != 31))
            {
                int data = ReadEE((ushort)writeEEAddr);
                if (data != writeEEData)
                {
                    MainWindowVM.MTPchackFailed = true;
                    Log.Information(" MTP Write failure！\r\nMTP address: " + writeEEAddr.ToString() + "\r\nExcept value: " + writeEEData.ToString("X4") + "(" + writeEEData.ToString() + ")" + "\r\nRead value: " + data.ToString("X4") + "(" + data.ToString() + ")" + "\r\n");
                }
            }

        }

        public static void WriteEE28And31(int writeEEAddr, int writeEEData)
        {
            if ((writeEEAddr == 28) | (writeEEAddr == 31))
            {

                unlockTrim();
            }

            if (!WriteReg(163, 0, 2))
            {
                return;
            }

            if (!WriteReg(162, writeEEAddr, 2))
            {
                return;
            }

            if (!WriteReg(161, 3, 2))
            {
                return;
            }




            if (!WriteReg(163, writeEEData, 2))
            {
                return;
            }

            if (!WriteReg(162, writeEEAddr, 2))
            {
                return;
            }

            WriteReg(161, 5, 2);

            if ((writeEEAddr == 28) | (writeEEAddr == 31))
            {
                lockTrim();
            }
            if ((writeEEAddr != 28) & (writeEEAddr != 31))
            {
                int data = ReadEE((ushort)writeEEAddr);
                if (data != writeEEData)
                {
                    Log.Information(" EEPROM数据验证不匹配\r\nEEPROM地址: " + writeEEAddr.ToString() + "\r\n期望值: " + writeEEData.ToString("X4") + "(" + writeEEData.ToString() + ")" + "\r\n读取值: " + data.ToString("X4") + "(" + data.ToString() + ")" + "\r\n");
                }
            }

        }


        public static void WriteEENoLog(int writeEEAddr, int writeEEData)
        {
            unlockTrim();

            if (!WriteRegNoLog(163, writeEEData, 2))
            {
                MainWindowVM.MTPchackFailed = true;
                return;
            }

            if (!WriteRegNoLog(162, writeEEAddr, 2))
            {
                MainWindowVM.MTPchackFailed = true;
                return;
            }

            WriteRegNoLog(161, 5, 2);

            lockTrim();
        }

        public static int ReadEE(ushort ReadEEAddr)
        {
            if ((ReadEEAddr == 0) || (ReadEEAddr == 1) || (ReadEEAddr == 2) ||
                (ReadEEAddr == 3) || (ReadEEAddr == 5) || (ReadEEAddr == 28) || (ReadEEAddr == 31))
            {
                ///MessageBox.Show("此寄存器未开放(Skip)");
                return 0;
            }
            return ReadReg(ReadEEAddr, 2);
        }

        public static int ReadEENoLog(ushort ReadEEAddr) => ReadRegNoLog(ReadEEAddr, 2);

        /// <summary>
        /// 通过检测芯片温度结果判断I2C是否异常,正常测试环境下温度不可能超过-60℃ ~ 190℃，这样ADC的结果就是7 ~ 507个ADC量化值,如果读值在7 ~ 507cts之间，认为芯片正常，I2C通讯正常
        /// </summary>
        /// <returns></returns>
        public static bool IsI2COk() => TryReadRegNoLog(138, 2, out int res) && res > 7 && res < 507;

        /// <summary>
        /// 存在未知Bug，多通讯几次就能成功
        /// </summary>
        /// <returns></returns>
        public static bool IsI2COkMutil() => IsI2COk() ? true : (IsI2COk() || IsI2COk());
    }
}
